package com.kgc.crowd.distributioncrowdmembermanager.controller;

import com.kgc.crow.distributioncrowdcommon.api.DataBaseOperationRemoteService;
import com.kgc.crow.distributioncrowdcommon.api.RedisOperationRemoteService;
import com.kgc.crow.distributioncrowdcommon.pojo.MemberLaunchInfoPO;
import com.kgc.crow.distributioncrowdcommon.pojo.MemberPo;
import com.kgc.crow.distributioncrowdcommon.pojo.ResultEntity;
import com.kgc.crow.distributioncrowdcommon.util.CrowdConstant;
import com.kgc.crow.distributioncrowdcommon.util.CrowdUtils;
import com.kgc.crow.distributioncrowdcommon.vo.MemberSignSuccessVO;
import com.kgc.crow.distributioncrowdcommon.vo.MemberVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Objects;

@RestController
public class MemberController {

    @Value("${distribution.crowd.code.length}")
    int length;
    @Value("${distribution.crowd.redis.timeoutMinute}")
    Integer timeoutMinute;
    @Value("${distribution.crowd.accessKeyId}")
    String accessKeyId;
    @Value("${distribution.crowd.secret}")
    String secret;

    @Resource
    RedisOperationRemoteService redisOperationRemoteService;

    @Resource
    DataBaseOperationRemoteService dataBaseOperationRemoteService;

    @Resource
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @RequestMapping("/member/manager/send/code")
    public ResultEntity<String> sendCode(@RequestParam("phoneNum") String phoneNum) {
        if (!CrowdUtils.strEffectiveCheck(phoneNum)) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_PHONE_NUM_INVALID);
        }
        // 1.生成验证码
        String randomCode = CrowdUtils.randomCode(length);

        //2.保存到Redis
        String normalKey = CrowdConstant.REDIS_RANDOM_CODE_PREFIX + phoneNum;
        ResultEntity<String> stringResultEntity = redisOperationRemoteService.saveNormalStringKeyValue(normalKey, randomCode, timeoutMinute);
        if(ResultEntity.FAILED.equals(stringResultEntity.getResult())){
            return stringResultEntity;
        }
        // 3.发送验证码到用户手机
        try {
            CrowdUtils.sendShortMessage(accessKeyId,secret,randomCode, phoneNum);
            return ResultEntity.successNoData();
        }catch (Exception ex){
            return ResultEntity.failed(ex.getMessage());
        }
    }

    @RequestMapping("/register")
    public ResultEntity<String> register(@RequestBody MemberVO memberVO){
        // 1.获取验证码数据并进行有效性检测
        String randomCode = memberVO.getRandomCode();
        if(!CrowdUtils.strEffectiveCheck(randomCode)) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_RANDOM_CODE_LENGTH_INVALID);
        }
        // 2.获取手机号数据并进行有效性检测
        String phoneNum = memberVO.getPhoneNum();
        if(!CrowdUtils.strEffectiveCheck(phoneNum)) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_PHONE_NUM_INVALID);
        }
        // 3.拼接Redis存储验证码的KEY
        String randomCodeKey = CrowdConstant.REDIS_RANDOM_CODE_PREFIX + phoneNum;
        // 4.远程调用redis-provider的方法查询对应验证码
        ResultEntity<String> randomCodeRemoteResultEntity = redisOperationRemoteService.retrieveStringValueByStringKey(randomCodeKey);
        if(ResultEntity.FAILED.equals(randomCodeRemoteResultEntity.getResult())) {
            return randomCodeRemoteResultEntity;
        }
        // 5.检查远程获取的验证码是否存在
        String randomCodeRemote = randomCodeRemoteResultEntity.getData();
        if(!CrowdUtils.strEffectiveCheck(randomCodeRemote)) {

            return ResultEntity.failed(CrowdConstant.MESSAGE_CODE_NOT_EXISTS);

        }
        // 6.将“表单验证码”和“Redis验证码”进行比较
        if(!Objects.equals(randomCode, randomCodeRemote)) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_CODE_NOT_MATCH);
        }
        // 7.检测登录账号是否被占用
        String loginacct = memberVO.getLoginacct();
        ResultEntity<Integer> loignAcctCountResultEntity = dataBaseOperationRemoteService.retrieveLoignAcctCount(loginacct);
        if(ResultEntity.FAILED.equals(loignAcctCountResultEntity.getResult())) {
            return randomCodeRemoteResultEntity;
        }
        Integer loignAcctCount = loignAcctCountResultEntity.getData();
        if(loignAcctCount > 0) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_LOGIN_ACCT_ALREADY_IN_USE);
        }
        // 8.加密
        String userpswd = memberVO.getUserpswd();
        if(!CrowdUtils.strEffectiveCheck(userpswd)) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_CODE_INVALID);
        }
        userpswd = bCryptPasswordEncoder.encode(userpswd);
        memberVO.setUserpswd(userpswd);
        // 9.将VO对象转换为PO对象
        MemberPo memberPO = new MemberPo();
        BeanUtils.copyProperties(memberVO, memberPO);
        // 10.执行保存操作
        ResultEntity<String> saveMemberRemoteResultEntity = dataBaseOperationRemoteService.saveMemberRemote(memberPO);

        return saveMemberRemoteResultEntity;
    }

    @RequestMapping("/login")
    public ResultEntity<MemberSignSuccessVO> login(
            @RequestParam("loginAcct") String loginAcct,
            @RequestParam("userPswd") String userPswd) {
        // 1.根据登录账号查询数据库获取MemberPO对象
        ResultEntity<MemberPo> resultEntity = dataBaseOperationRemoteService.retrieveMemberByLoginAcct(loginAcct);
        if(ResultEntity.FAILED.equals(resultEntity.getResult())) {
            return ResultEntity.failed(resultEntity.getMessage());
        }
        // 2.获取MemberPO对象
        MemberPo memberPO = resultEntity.getData();
        // 3.检查MemberPO对象是否为空
        if(memberPO == null) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_LOGIN_FAILED);
        }
        // 4.获取从数据库查询得到的密码
        String userpswdDatabase = memberPO.getUserpswd();
        // 5.比较密码
        boolean matcheResult = bCryptPasswordEncoder.matches(userPswd, userpswdDatabase);
        if(!matcheResult) {
            return ResultEntity.failed(CrowdConstant.MESSAGE_LOGIN_FAILED);
        }
        // 6.生成token
        String token = CrowdUtils.generateToken();
        // 7.从MemberPO对象获取memberId
        String memberId = memberPO.getId() + "";
        // 8.将token和memberId存入Redis
        ResultEntity<String> resultEntitySaveToken = redisOperationRemoteService.saveNormalStringKeyValue(token, memberId, 30);
        if(ResultEntity.FAILED.equals(resultEntitySaveToken.getResult())) {
            return ResultEntity.failed(resultEntitySaveToken.getMessage());
        }
        // 9.封装MemberSignSuccessVO对象
        MemberSignSuccessVO memberSignSuccessVO = new MemberSignSuccessVO();

        BeanUtils.copyProperties(memberPO, memberSignSuccessVO);

        memberSignSuccessVO.setToken(token);
        // 10.返回结果
        return ResultEntity.successWithData(memberSignSuccessVO);
    }

    @RequestMapping("/logout")
    public ResultEntity<String> logout(@RequestParam("token") String token) {
        return redisOperationRemoteService.removeByKey(token);
    }

    @RequestMapping("/retrieve/member/launch/info/by/member/token")
    public ResultEntity<MemberLaunchInfoPO> resultEntity(@RequestParam("token") String token) {
        ResultEntity<String> stringResultEntity = redisOperationRemoteService.retrieveStringValueByStringKey(token);
        if(stringResultEntity.getResult().equals(ResultEntity.FAILED)){
            return ResultEntity.failed(stringResultEntity.getMessage());
        }
        String memberIdstr = stringResultEntity.getData();
        Integer memeberId = Integer.parseInt(memberIdstr);
        ResultEntity<MemberLaunchInfoPO> memberLaunchInfoPOResultEntity = dataBaseOperationRemoteService.resultEntity(memeberId);
        return memberLaunchInfoPOResultEntity;
    }
}
